package com.woniuxy.commons.interceptor;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.woniuxy.commons.annotations.RequirePermission;
import com.woniuxy.commons.enums.ResultCodeEnum;
import com.woniuxy.commons.enums.TokenEnum;
import com.woniuxy.commons.result.Result;
import com.woniuxy.commons.service.auth.AuthService;
import com.woniuxy.commons.utils.JWTUtil;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;

/**
 * <P> @Author: ideaAdmin
 * <P> TODO: Class
 * <P> TODO: 鉴权的拦截器
 * <P> Date: 2022/3/30:14:32
 * <P> Description:
 */
@Component
public class PermissionInterceptor extends HandlerInterceptorAdapter {

    /**
     * TODO 认证模块的service调用
     */
    @Resource
    /**
     *
     * TODO 延迟加载
     */
    @Lazy
    private AuthService authService;

    /**
     * TODO: 调用controller之前执行代码
     *          返回值true 表示放行 false表示拦截
     *          拦截器会拦截那些请求:普通请求、静态资源
     **/
    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        //TODO: 1.获取到马上要调用的方法( Controller 中的方法)
        //TODO 请求当前请求 是否是普通的http请求

        System.out.println("拦截器访问的路径:" + request.getRequestURI());
        System.out.println("拦截器访问的token:" + request.getHeader("authorization"));
        System.out.println("拦截器访问的 refreshToken:" + request.getHeader("refreshToken"));

        if (handler instanceof HandlerMethod) {
            HandlerMethod handlerMethod = (HandlerMethod) handler;
            //获取到要调用的方法
            Method method = handlerMethod.getMethod();

            //TODO: 2.判断方法上是否有权限的注解
            if (method.isAnnotationPresent(RequirePermission.class)) {
                RequirePermission rp = method.getDeclaredAnnotation(RequirePermission.class);

                //TODO: 3.如果有则获取到注解的值
                String perms = rp.value();

                //TODO: 4.通过token、redis得到当前用户的账号
                String token = request.getHeader("authorization");

                //判断token是否为null

                if (token == null ||
                        token.length() == 0 ||
                        "null".equals(token) ||
                        JWTUtil.verify(token).equals((TokenEnum.TOKEN_BAD))) {
                    //TODO: 去登陆


                    response.setContentType("application/json;charset=utf-8");

                    String data = new ObjectMapper()
                            .writeValueAsString
                                    (Result.build(null, ResultCodeEnum.NO_LOGIN));
                    response.getWriter().write(data);
                    return false;
                }

                //TODO: 5.通过openfeign 调用auth的鉴权方法 参数：账号 权限

                // 传入 refreshToken 获得当前用户的角色
                String refreshToken = request.getHeader("refreshToken");
                Result<Object> result = authService.hasPerms(refreshToken, perms);

                //TODO: 6.根据鉴权的结果决定是否放行 500 不放行
                if (result.getCode().equals(ResultCodeEnum.FAIL.getCode())) {

                    response.setContentType("application/json;charset=utf-8");

                    String data = new ObjectMapper().writeValueAsString(result);
                    response.getWriter().write(data);
                    return false;
                }

            }
        }

        return true;
    }
}
